package cn.com.commons.utils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class CommonUtils {

	private static final String[][] CODES = { { "&", "&#38;" },
			{ "<", "&#60;" }, { ">", "&#62;" }, { "\"", "&#34;" },
			// {"","&#174;"},
			{ "\u00ae", "&#174;" }, { " ", "&nbsp;" },
			// {"","&#169;"}
			{ "\u00a9", "&#169;" } };

	public static Integer safeToInteger(String val) {
		if (StringUtil.isNotBlank(val)) {
			return new Integer("0");
		}
		return new Integer(validNum(val));
	}

	public static BigDecimal safeToBigDecimal(Object val) {
		if (val == null) {
			return new BigDecimal("0.0");
		}
		return (BigDecimal) val;
	}

	public static BigDecimal convertToBigDecimal(String val) {
		if (StringUtil.isNotBlank(val)) {
			return new BigDecimal("0.0");
		}
		return new BigDecimal(validNum(val));
	}

	public static String validNum(String val) {
		String reVal = val.replaceAll(",", "");
		reVal = reVal.replaceAll("^-$", "");
		if (StringUtil.isNotBlank(reVal)) {
			return "0";
		}
		return reVal;
	}

	public static String safeToString(Object val) {
		if (val == null) {
			return "";
		}
		return val.toString();
	}

	public static String covertToBR(String value) {
		if (value == null) {
			return "";
		}
		return value.replaceAll("\r[\\n]", "<br>");
	}

	public static String escapeDoc(String doc) {
		String tmpStr = new String(doc);
		StringBuffer str = new StringBuffer(doc);
		for (int i = 0; i < CODES.length; i++) {
			int index = -1;
			boolean running = true;
			while (running) {
				index = tmpStr.indexOf(CODES[i][0]);
				if (index < 0) {
					running = false;
					break;
				}
				if (!(index + 1 >= tmpStr.length())) {
					if (tmpStr.charAt(index + 1) == '#')
						break;
				}
				str.setCharAt(index, CODES[i][1].charAt(0));
				str.insert(index + 1, CODES[i][1].substring(1));
				tmpStr = str.toString();
			}
		}
		return tmpStr;
	}

	public static String formatDate(Date date, String pattern) {
		if (date == null) {
			return "";
		}

		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	public static Date convertToDate(String date, String pattern)
			throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		Date sd = sdf.parse(date);
		return sd;
	}

	public static Calendar convertToCalendar(String date, String pattern)
			throws Exception {
		Date sd = convertToDate(date, pattern);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(sd);
		return calendar;
	}

	public static String getCurrentYear() {
		Calendar c = getCurrentCalendar();
		return safeToString(c.get(Calendar.YEAR));
	}

	public static String getCurrentMonth() {
		Calendar c = getCurrentCalendar();
		return safeToString(c.get(Calendar.MONTH) + 1);
	}

	public static String getCurrentDate() {
		Calendar c = getCurrentCalendar();
		return safeToString(c.get(Calendar.DATE));
	}

	public static Calendar getCurrentCalendar() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		return cal;
	}

	public static String getCurrent10Date() {
		return CommonUtils.getCurrentYear() + "/"
				+ formatNumber(CommonUtils.getCurrentMonth(), 2) + "/"
				+ formatNumber(CommonUtils.getCurrentDate(), 2);
	}

	public static Timestamp getCurrentDateTime() {
		Timestamp sysdate = new Timestamp(System.currentTimeMillis());
		return sysdate;
	}

	public static int diffMonth(Date formerDate, Date latterDate) {
		Calendar fCalendar = Calendar.getInstance();
		fCalendar.setTime(formerDate);
		Calendar lCalendar = Calendar.getInstance();
		lCalendar.setTime(latterDate);

		int cnt = 0;
		while (fCalendar.get(Calendar.YEAR) != lCalendar.get(Calendar.YEAR)
				|| fCalendar.get(Calendar.MONTH) != lCalendar
						.get(Calendar.MONTH)) {
			fCalendar.add(Calendar.MONTH, 1);
			cnt++;
		}
		return cnt;
	}

	public static String formatDecimal(BigDecimal decimal, String pattern) {
		if (decimal == null) {
			return "";
		}

		DecimalFormat df = new DecimalFormat(pattern);
		return df.format(decimal);
	}

	public static String noFormatDecimal(BigDecimal decimal) {
		if (decimal == null) {
			return "";
		}
		return decimal.toString();
	}

	public static BigDecimal multiply(BigDecimal Multiplicand,
			BigDecimal Multiplier) {
		return safeToBigDecimal(Multiplicand).multiply(
				safeToBigDecimal(Multiplier));
	}

	public static BigDecimal add(BigDecimal Addend, BigDecimal adder) {
		return safeToBigDecimal(Addend).add(safeToBigDecimal(adder));
	}

	public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor) {
		return divide(dividend, divisor, 20, BigDecimal.ROUND_HALF_UP);
	}

	public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor,
			int scale, int roundingMode) {
		return safeToBigDecimal(dividend).divide(safeToBigDecimal(divisor),
				scale, roundingMode);
	}

	@SuppressWarnings("unchecked")
	public static String jsonFromMap(Map<String, ?> map) {
		if (map == null || map.size() == 0) {
			return "{}";
		}

		StringBuilder sb = new StringBuilder("{");
		for (String key : map.keySet()) {
			Object val = map.get(key);
			String keyPart = key + ":";
			String valPart = "";

			if (val instanceof Map) {
				valPart = jsonFromMap((Map<String, Object>) val);
			} else if (val instanceof List) {
				valPart = jsonFromList((List<Object>) val);
			} else {
				valPart = "'" + val.toString() + "'";
			}
			sb.append(keyPart + valPart);
			sb.append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append("}");
		return sb.toString();
	}

	@SuppressWarnings("unchecked")
	public static String jsonFromList(List<?> list) {
		if (list == null || list.size() == 0) {
			return "[]";
		}

		StringBuilder sb = new StringBuilder("[");
		for (Object val : list) {
			String valPart = "";

			if (val instanceof Map) {
				valPart = jsonFromMap((Map<String, Object>) val);
			} else if (val instanceof List) {
				valPart = jsonFromList((List<Object>) val);
			} else {
				valPart = "'" + val.toString() + "'";
			}
			sb.append(valPart);
			sb.append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append("]");
		return sb.toString();
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> T getModel(Map<String, T> map, String key, Class type) {
		T model = map.get(key);
		if (model == null) {
			try {
				T newModel = (T) type.newInstance();
				map.put(key, newModel);
				return newModel;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return model;
	}

	public static Field getFieldSilent(Class<?> clz, String fieldName) {
		try {
			return clz.getDeclaredField(fieldName);
		} catch (NoSuchFieldException e) {
			return null;
		}
	}

	public static Field findField(Class<?> modelClz, String fieldName)
			throws Exception {
		Field modelField = getFieldSilent(modelClz, fieldName);
		if (modelField != null) {
			return modelField;
		} else if (hasSuperClz(modelClz)) {
			return findField(modelClz.getSuperclass(), fieldName);
		}
		return null;
	}

	public static boolean hasSuperClz(Class<?> clz) {
		return (!"Object".equals(clz.getSuperclass().getSimpleName()));
	}

	public static String formatNumber(String num, int count) {
		while (num.length() < count) {
			num = "0" + num;
		}
		return num;
	}

	/**
	 * md5
	 * 
	 * @param str
	 * @return
	 */
	public static String md5Encode(String str) {
		StringBuffer buf = new StringBuffer();
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(str.getBytes());
			byte bytes[] = md5.digest();
			for (int i = 0; i < bytes.length; i++) {
				String s = Integer.toHexString(bytes[i] & 0xff);
				if (s.length() == 1) {
					buf.append("0");
				}
				buf.append(s);
			}

		} catch (Exception ex) {
		}
		return buf.toString();
	}

}
